Currency exchange example¶
Dataset used is the currency enchange with respect to USD dollars, from daily measurements from the last 2 years (2017-2018).
Currencies used:
- Reference: USA
- Canadian dollar (CAD)
- Euro (EUR)
- Japanese yen (JPY)
- Great British pound (GBP)
- Swiss franc (CHF)
- Austrial dollar (AUD)
- Hong Kong dollar (HKD)
- New Zealand dollar (NZD)
- South Korean won (KRW)
- Mexican peso (MXN)
Please see our publication at https://doi.org/10.1109/ICASSP40776.2020.9054102 for a full description of this data set and the interpretations of our results.
In [1]:
import mogptk
import torch
import numpy as np
import pandas as pd
torch.manual_seed(1);
Data loading¶
In [2]:
column_names = ['EUR/USD', 'CAD/USD', 'JPY/USD', 'GBP/USD', 'CHF/USD',
'AUD/USD', 'HKD/USD','NZD/USD', 'KRW/USD','MXN/USD']
dataset = mogptk.DataSet()
for names in column_names:
dataset.append(mogptk.LoadCSV('data/currency_exchange/final_dataset.csv',
x_col='Date', y_col=names))
dataset.filter('2017-01-03', '2018-01-01')
In [3]:
# Preprocess by randomly removing points and detrending
for i, channel in enumerate(dataset):
channel.transform(mogptk.TransformDetrend)
channel.transform(mogptk.TransformNormalize())
channel.remove_randomly(pct=0.3)
if i not in [0, 2, 5]:
channel.remove_range('2017-11-17', None)
# simulate sensor failure
dataset[1].remove_range('2017-03-31', '2017-05-01')
dataset[2].remove_range('2017-12-28', None)
dataset[3].remove_range('2017-07-20', '2017-09-08')
dataset[4].remove_range(None, '2017-01-31')
dataset[5].remove_range('2017-12-28', None)
dataset[7].remove_range(None, '2017-01-31')
In [4]:
dataset.plot();
In [5]:
n_trials = 3
Q = 3
init_method = 'BNSE'
method = 'Adam'
lr = 0.1
iters = 1000
Multi-output spectral mixture kernel¶
In [6]:
mosm_models = []
mosm_mae = np.zeros((n_trials,10))
mosm_rmse = np.zeros((n_trials,10))
mosm_mape = np.zeros((n_trials,10))
# experiment trials
for n in range(n_trials):
mosm_dataset = dataset.copy()
for i, channel in enumerate(mosm_dataset):
channel.remove_randomly(pct=0.3)
print('\nTrial', n+1, 'of', n_trials)
mosm = mogptk.MOSM(mosm_dataset, Q=Q)
mosm.init_parameters(init_method)
mosm.train(method=method, lr=lr, iters=iters, verbose=True)
mosm_models.append(mosm)
print('=' * 50)
error = mogptk.error(mosm, per_channel=True)[0]
mosm_mae[n,:] = np.array([item['MAE'] for item in error])
mosm_rmse[n,:] = np.array([item['RMSE'] for item in error])
mosm_mape[n,:] = np.array([item['MAPE'] for item in error])
Trial 1 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: MultiOutputSpectralMixtureKernel
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 160
‣ Training points: 1067
‣ Iterations: 1000
0/1000 0:00:16 loss= 372.156 (warmup)
2/1000 0:01:17 loss= 387.18
18/1000 0:01:20 loss= 234.751
94/1000 0:01:30 loss= -166.447
171/1000 0:01:40 loss= -204.738
247/1000 0:01:50 loss= -236.755
322/1000 0:02:00 loss= -245.181
397/1000 0:02:10 loss= -199.653
473/1000 0:02:20 loss= -259.147
548/1000 0:02:30 loss= -267.594
624/1000 0:02:40 loss= -267.126
700/1000 0:02:50 loss= -278.228
776/1000 0:03:00 loss= -166.826
850/1000 0:03:10 loss= -286.286
925/1000 0:03:20 loss= -316.283
1000/1000 0:03:29 loss= -305.608
Optimization finished in 3 minutes 29 seconds
==================================================
Trial 2 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: MultiOutputSpectralMixtureKernel
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 160
‣ Training points: 1080
‣ Iterations: 1000
0/1000 0:00:16 loss= 368.765 (warmup)
2/1000 0:01:17 loss= 384.723
21/1000 0:01:20 loss= 216.958
98/1000 0:01:30 loss= -142.257
174/1000 0:01:40 loss= -226.501
250/1000 0:01:50 loss= -249.294
325/1000 0:02:00 loss= -258.298
401/1000 0:02:10 loss= -292.801
477/1000 0:02:20 loss= -303.31
552/1000 0:02:30 loss= -312.979
628/1000 0:02:40 loss= -286.96
704/1000 0:02:50 loss= -325.937
780/1000 0:03:00 loss= -330.992
856/1000 0:03:10 loss= -362.705
932/1000 0:03:20 loss= -372.888
1000/1000 0:03:29 loss= -359.156
Optimization finished in 3 minutes 29 seconds
==================================================
Trial 3 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: MultiOutputSpectralMixtureKernel
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 160
‣ Training points: 1087
‣ Iterations: 1000
0/1000 0:00:16 loss= 364.808 (warmup)
2/1000 0:01:18 loss= 364.755
18/1000 0:01:20 loss= 215.453
92/1000 0:01:30 loss= -145.425
167/1000 0:01:40 loss= -195.586
242/1000 0:01:50 loss= -233.809
318/1000 0:02:00 loss= -262.34
393/1000 0:02:10 loss= -265.013
469/1000 0:02:20 loss= -279.058
544/1000 0:02:30 loss= -286.797
619/1000 0:02:40 loss= -288.758
693/1000 0:02:50 loss= -287.868
768/1000 0:03:00 loss= -296.887
844/1000 0:03:10 loss= -291.105
919/1000 0:03:20 loss= -243.156
995/1000 0:03:30 loss= -294.737
1000/1000 0:03:30 loss= -297.921
Optimization finished in 3 minutes 30 seconds
==================================================
In [7]:
pd.DataFrame(np.c_[mosm_mae.mean(1), mosm_rmse.mean(1), mosm_mape.mean(1),
mosm_mae.std(1), mosm_rmse.std(1), mosm_mape.std(1)],
columns=['MAE', 'RMSE', 'MAPE', 'MAE std', 'RMSE std', 'MAPE std'])
Out[7]:
| MAE | RMSE | MAPE | MAE std | RMSE std | MAPE std | |
|---|---|---|---|---|---|---|
| 0 | 1.424521 | 2.134517 | 0.816759 | 3.948284 | 5.973529 | 0.381060 |
| 1 | 0.762996 | 1.003298 | 0.730678 | 1.990932 | 2.622035 | 0.303361 |
| 2 | 1.143211 | 1.502700 | 0.760170 | 3.157059 | 4.145439 | 0.300203 |
In [8]:
best_mosm = mosm_models[np.argmin(mosm_mape.mean(1))]
best_mosm.predict()
best_mosm.plot_prediction();
Cross spectral mixture kernel¶
In [9]:
csm_models = []
csm_mae = np.zeros((n_trials,10))
csm_rmse = np.zeros((n_trials,10))
csm_mape = np.zeros((n_trials,10))
for n in range(n_trials):
csm_dataset = dataset.copy()
for i, channel in enumerate(csm_dataset):
channel.remove_randomly(pct=0.3)
print('\nTrial', n+1, 'of', n_trials)
csm = mogptk.CSM(csm_dataset, Q=Q)
csm.init_parameters(init_method)
csm.train(method=method, lr=lr, iters=iters, verbose=True)
csm_models.append(csm)
print('=' * 50)
error = mogptk.error(csm, per_channel=True)[0]
csm_mae[n,:] = np.array([item['MAE'] for item in error])
csm_rmse[n,:] = np.array([item['RMSE'] for item in error])
csm_mape[n,:] = np.array([item['MAPE'] for item in error])
Trial 1 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: MixtureKernel['CrossSpectralKernel', 'CrossSpectralKernel', 'CrossSpectralKernel']
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 76
‣ Training points: 1075
‣ Iterations: 1000
0/1000 0:00:27 loss= 601.512 (warmup)
2/1000 0:02:40 loss= 453.24
55/1000 0:02:50 loss= 70.6357
109/1000 0:03:00 loss= -76.5361
163/1000 0:03:10 loss= -125.643
218/1000 0:03:20 loss= -145.775
272/1000 0:03:30 loss= -150.338
327/1000 0:03:40 loss= -155.408
381/1000 0:03:50 loss= -161.76
436/1000 0:04:00 loss= -162.39
490/1000 0:04:10 loss= -162.668
544/1000 0:04:20 loss= -162.338
599/1000 0:04:30 loss= -163.379
654/1000 0:04:40 loss= -164.088
708/1000 0:04:50 loss= -164.429
763/1000 0:05:00 loss= -164.581
818/1000 0:05:10 loss= -163.493
873/1000 0:05:20 loss= -164.873
927/1000 0:05:30 loss= -165.094
981/1000 0:05:40 loss= -165.068
1000/1000 0:05:43 loss= -164.878
Optimization finished in 5 minutes 43 seconds
==================================================
Trial 2 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: MixtureKernel['CrossSpectralKernel', 'CrossSpectralKernel', 'CrossSpectralKernel']
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 76
‣ Training points: 1088
‣ Iterations: 1000
0/1000 0:00:27 loss= 598.199 (warmup)
2/1000 0:02:41 loss= 463.294
51/1000 0:02:50 loss= 79.7187
106/1000 0:03:00 loss= -64.6969
161/1000 0:03:10 loss= -139.369
216/1000 0:03:20 loss= -157.34
272/1000 0:03:30 loss= -178.806
327/1000 0:03:40 loss= -179.746
382/1000 0:03:50 loss= -181.35
438/1000 0:04:00 loss= -182.51
492/1000 0:04:10 loss= -183.386
548/1000 0:04:20 loss= -183.482
603/1000 0:04:30 loss= -185.001
659/1000 0:04:40 loss= -180.207
714/1000 0:04:50 loss= -184.017
769/1000 0:05:00 loss= -184.985
824/1000 0:05:10 loss= -181.069
879/1000 0:05:20 loss= -184.788
935/1000 0:05:30 loss= -185.216
990/1000 0:05:40 loss= -185.68
1000/1000 0:05:41 loss= -184.441
Optimization finished in 5 minutes 41 seconds
==================================================
Trial 3 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: MixtureKernel['CrossSpectralKernel', 'CrossSpectralKernel', 'CrossSpectralKernel']
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 76
‣ Training points: 1084
‣ Iterations: 1000
0/1000 0:00:27 loss= 604.508 (warmup)
2/1000 0:02:41 loss= 454.473
48/1000 0:02:50 loss= 84.3161
103/1000 0:03:00 loss= -99.7946
157/1000 0:03:10 loss= -149.296
212/1000 0:03:20 loss= -158.207
266/1000 0:03:30 loss= -160.22
321/1000 0:03:40 loss= -160.419
375/1000 0:03:50 loss= -164.288
430/1000 0:04:00 loss= -167.108
484/1000 0:04:10 loss= -165.533
539/1000 0:04:20 loss= -169.2
593/1000 0:04:30 loss= -169.546
647/1000 0:04:40 loss= -169.71
701/1000 0:04:50 loss= -171.132
756/1000 0:05:00 loss= -171.155
811/1000 0:05:10 loss= -171.649
865/1000 0:05:20 loss= -171.862
920/1000 0:05:30 loss= -171.931
975/1000 0:05:40 loss= -172.304
1000/1000 0:05:44 loss= -171.657
Optimization finished in 5 minutes 44 seconds
==================================================
In [10]:
pd.DataFrame(np.c_[csm_mae.mean(1), csm_rmse.mean(1), csm_mape.mean(1),
csm_mae.std(1), csm_rmse.std(1), csm_mape.std(1)],
columns=['MAE', 'RMSE', 'MAPE', 'MAE std', 'RMSE std', 'MAPE std'])
Out[10]:
| MAE | RMSE | MAPE | MAE std | RMSE std | MAPE std | |
|---|---|---|---|---|---|---|
| 0 | 0.990018 | 1.289088 | 0.828820 | 2.531145 | 3.291015 | 0.384047 |
| 1 | 0.894034 | 1.182334 | 0.813442 | 2.245169 | 2.974195 | 0.360703 |
| 2 | 0.981467 | 1.295573 | 0.802904 | 2.486301 | 3.297500 | 0.344625 |
In [11]:
best_csm = csm_models[np.argmin(csm_mape.mean(1))]
best_csm.predict()
best_csm.plot_prediction();
Linear model of coregionalization with spectral mixture kernels¶
In [12]:
smlmc_models = []
smlmc_mae = np.zeros((n_trials,10))
smlmc_rmse = np.zeros((n_trials,10))
smlmc_mape = np.zeros((n_trials,10))
for n in range(n_trials):
smlmc_dataset = dataset.copy()
for i, channel in enumerate(smlmc_dataset):
channel.remove_randomly(pct=0.3)
print('\nTrial', n+1, 'of', n_trials)
smlmc = mogptk.SM_LMC(smlmc_dataset, Q=Q)
smlmc.init_parameters(init_method)
smlmc.train(method=method, lr=lr, iters=iters, verbose=True)
smlmc_models.append(smlmc)
print('=' * 50)
error = mogptk.error(smlmc, per_channel=True)[0]
smlmc_mae[n,:] = np.array([item['MAE'] for item in error])
smlmc_rmse[n,:] = np.array([item['RMSE'] for item in error])
smlmc_mape[n,:] = np.array([item['MAPE'] for item in error])
Trial 1 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: LinearModelOfCoregionalizationKernel['SpectralKernel', 'SpectralKernel', 'SpectralKernel']
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 46
‣ Training points: 1079
‣ Iterations: 1000
0/1000 0:00:14 loss= 589.172 (warmup)
2/1000 0:01:52 loss= 565.024
68/1000 0:02:00 loss= 214.408
170/1000 0:02:10 loss= 124.878
272/1000 0:02:20 loss= 109.457
375/1000 0:02:30 loss= 105.879
477/1000 0:02:40 loss= 104.072
577/1000 0:02:50 loss= 103.038
677/1000 0:03:00 loss= 102.352
777/1000 0:03:10 loss= 101.886
878/1000 0:03:20 loss= 101.505
980/1000 0:03:30 loss= 101.196
1000/1000 0:03:32 loss= 101.139
Optimization finished in 3 minutes 32 seconds
==================================================
Trial 2 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: LinearModelOfCoregionalizationKernel['SpectralKernel', 'SpectralKernel', 'SpectralKernel']
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 46
‣ Training points: 1089
‣ Iterations: 1000
0/1000 0:00:15 loss= 608.623 (warmup)
2/1000 0:01:53 loss= 587.874
67/1000 0:02:00 loss= 226.184
163/1000 0:02:10 loss= 145.649
260/1000 0:02:20 loss= 94.631
357/1000 0:02:30 loss= -20.3752
453/1000 0:02:40 loss= -45.6881
551/1000 0:02:50 loss= -47.8884
649/1000 0:03:00 loss= -48.8847
745/1000 0:03:10 loss= -50.3853
841/1000 0:03:20 loss= -103.072
938/1000 0:03:30 loss= -115.846
1000/1000 0:03:36 loss= -117.359
Optimization finished in 3 minutes 36 seconds
==================================================
Trial 3 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: LinearModelOfCoregionalizationKernel['SpectralKernel', 'SpectralKernel', 'SpectralKernel']
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 46
‣ Training points: 1092
‣ Iterations: 1000
0/1000 0:00:14 loss= 593.533 (warmup)
2/1000 0:01:52 loss= 572.904
64/1000 0:02:00 loss= 218.689
150/1000 0:02:10 loss= 145.44
238/1000 0:02:20 loss= 121.193
323/1000 0:02:30 loss= 116.266
408/1000 0:02:40 loss= 114.072
493/1000 0:02:50 loss= 112.8
577/1000 0:03:00 loss= 111.967
662/1000 0:03:10 loss= 111.359
745/1000 0:03:20 loss= 110.914
828/1000 0:03:30 loss= 110.567
922/1000 0:03:40 loss= 110.265
1000/1000 0:03:48 loss= 110.071
Optimization finished in 3 minutes 48 seconds
==================================================
In [13]:
pd.DataFrame(np.c_[smlmc_mae.mean(1), smlmc_rmse.mean(1), smlmc_mape.mean(1),
smlmc_mae.std(1), smlmc_rmse.std(1), smlmc_mape.std(1)],
columns=['MAE', 'RMSE', 'MAPE', 'MAE std', 'RMSE std', 'MAPE std'])
Out[13]:
| MAE | RMSE | MAPE | MAE std | RMSE std | MAPE std | |
|---|---|---|---|---|---|---|
| 0 | 1.138076 | 1.406304 | 0.849786 | 3.030571 | 3.721089 | 0.286675 |
| 1 | 1.265233 | 1.480022 | 0.742775 | 3.370088 | 3.888276 | 0.308673 |
| 2 | 1.183561 | 1.504745 | 0.882608 | 3.113238 | 3.930786 | 0.271166 |
In [14]:
best_smlmc = smlmc_models[np.argmin(smlmc_mape.mean(1))]
best_smlmc.predict()
best_smlmc.plot_prediction();
Independent spectral mixture kernels¶
In [15]:
sm_models = []
sm_mae = np.zeros((n_trials,10))
sm_rmse = np.zeros((n_trials,10))
sm_mape = np.zeros((n_trials,10))
for n in range(n_trials):
sm_dataset = dataset.copy()
for i, channel in enumerate(sm_dataset):
channel.remove_randomly(pct=0.3)
print('\nTrial', n+1, 'of', n_trials)
sm = mogptk.SM(sm_dataset, Q=Q)
sm.init_parameters(init_method)
sm.train(method=method, lr=lr, iters=iters, verbose=True)
sm_models.append(sm)
print('=' * 50)
error = mogptk.error(sm, per_channel=True)[0]
sm_mae[n,:] = np.array([item['MAE'] for item in error])
sm_rmse[n,:] = np.array([item['RMSE'] for item in error])
sm_mape[n,:] = np.array([item['MAPE'] for item in error])
Trial 1 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: IndependentMultiOutputKernel
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 100
‣ Training points: 1080
‣ Iterations: 1000
0/1000 0:00:03 loss= 367.354 (warmup)
2/1000 0:00:17 loss= 345.31
41/1000 0:00:20 loss= 44.1248
189/1000 0:00:30 loss= -295.224
333/1000 0:00:40 loss= -334.987
478/1000 0:00:50 loss= -342.512
624/1000 0:01:00 loss= -349.572
774/1000 0:01:10 loss= -350.634
924/1000 0:01:20 loss= -351.051
1000/1000 0:01:25 loss= -351.158
Optimization finished in 1 minute 25 seconds
==================================================
Trial 2 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: IndependentMultiOutputKernel
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 100
‣ Training points: 1089
‣ Iterations: 1000
0/1000 0:00:03 loss= 366.976 (warmup)
2/1000 0:00:17 loss= 345.736
38/1000 0:00:20 loss= 68.7848
179/1000 0:00:30 loss= -245.04
320/1000 0:00:40 loss= -280.445
461/1000 0:00:50 loss= -290.327
601/1000 0:01:00 loss= -333.071
744/1000 0:01:10 loss= -339.146
886/1000 0:01:20 loss= -340.069
1000/1000 0:01:28 loss= -340.468
Optimization finished in 1 minute 28 seconds
==================================================
Trial 3 of 3
Starting optimization using Adam
‣ Model: Exact
‣ Kernel: IndependentMultiOutputKernel
‣ Likelihood: GaussianLikelihood
‣ Channels: 10
‣ Parameters: 100
‣ Training points: 1085
‣ Iterations: 1000
0/1000 0:00:03 loss= 373.695 (warmup)
2/1000 0:00:17 loss= 351.578
40/1000 0:00:20 loss= 52.5212
186/1000 0:00:30 loss= -283.434
331/1000 0:00:40 loss= -324.609
476/1000 0:00:50 loss= -342.426
622/1000 0:01:00 loss= -347.558
770/1000 0:01:10 loss= -348.355
918/1000 0:01:20 loss= -351.273
1000/1000 0:01:25 loss= -352.836
Optimization finished in 1 minute 25 seconds
==================================================
In [16]:
pd.DataFrame(np.c_[sm_mae.mean(1), sm_rmse.mean(1), sm_mape.mean(1),
sm_mae.std(1), sm_rmse.std(1), sm_mape.std(1)],
columns=['MAE', 'RMSE', 'MAPE', 'MAE std', 'RMSE std', 'MAPE std'])
Out[16]:
| MAE | RMSE | MAPE | MAE std | RMSE std | MAPE std | |
|---|---|---|---|---|---|---|
| 0 | 0.838421 | 1.181028 | 0.661005 | 2.251060 | 3.204024 | 0.311735 |
| 1 | 1.376325 | 1.953592 | 0.685324 | 3.886168 | 5.529192 | 0.349559 |
| 2 | 1.208032 | 1.667259 | 0.685434 | 3.364896 | 4.668012 | 0.347804 |
In [17]:
best_sm = sm_models[np.argmin(sm_mape.mean(1))]
best_sm.predict()
best_sm.plot_prediction();
Results¶
In [18]:
print('MAPE errors per model')
print('MOSM: %g ± %g' % (mosm_mape.mean(1).mean(), mosm_mape.mean(1).std()))
print('CSM: %g ± %g' % (csm_mape.mean(1).mean(), csm_mape.mean(1).std()))
print('SM-LMC: %g ± %g' % (smlmc_mape.mean(1).mean(), smlmc_mape.mean(1).std()))
print('SM: %g ± %g' % (sm_mape.mean(1).mean(), sm_mape.mean(1).std()))
MAPE errors per model MOSM: 0.769203 ± 0.0357181 CSM: 0.815055 ± 0.0106413 SM-LMC: 0.825056 ± 0.0597046 SM: 0.677255 ± 0.0114902
In [ ]: